package tools

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strings"
	"sync"

	"gopkg.in/yaml.v3"
)

// ReadFiles 读取json文件夹中所有的文件内容
func ReadFiles(suffix, dir string) ([]string, error) {
	var (
		files = make([]string, 0)
		mu    sync.Mutex
		wg    sync.WaitGroup
	)
	// 遍历目录及子目录
	err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.IsDir() || !isJSONFile(info.Name()) {
			return nil
		}
		wg.Add(1)
		go func(p string) {
			defer wg.Done()
			if err != nil {
				log.Printf("本地元数据文件解析失败 %s: %v", p, err)
				return
			}
			mu.Lock()
			fileName := filepath.Base(p)
			if strings.Contains(fileName, suffix) {
				fileName = strings.Replace(fileName, suffix, "", -1)
			}
			files = append(files, fileName)
			mu.Unlock()
		}(path)
		return nil
	})
	wg.Wait()
	return files, err
}

// ReadJsonDir 读取json文件夹中所有的文件内容
func ReadJsonDir(dirPath string) (map[string]map[string]interface{}, error) {
	var (
		metas = make(map[string]map[string]interface{})
		mu    sync.Mutex
		wg    sync.WaitGroup
	)
	// 遍历目录及子目录
	err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.IsDir() || !isJSONFile(info.Name()) {
			return nil
		}
		wg.Add(1)
		go func(p string) {
			defer wg.Done()
			content, err := ReadArrayJsonFile(p)
			if err != nil {
				log.Printf("本地元数据文件解析失败 %s: %v", p, err)
				return
			}
			mu.Lock()
			fileName := filepath.Base(p)
			if strings.Contains(fileName, ".json") {
				fileName = strings.Replace(fileName, ".json", "", -1)
			}
			metas[fileName] = content
			mu.Unlock()
		}(path)
		return nil
	})
	wg.Wait()
	return metas, err
}

// ReadArrayJsonFile 读取json文件内容
func ReadArrayJsonFile(filePath string) (map[string]interface{}, error) {
	data, err := os.ReadFile(filePath)
	if err != nil {
		return nil, fmt.Errorf("文件读取失败: %w", err)
	}
	var content map[string]interface{}
	if err := json.Unmarshal(data, &content); err != nil {
		return nil, fmt.Errorf("JSON解析失败: %w", err)
	}
	return content, nil
}

// isJSONFile 是否是json文件
func isJSONFile(filename string) bool {
	ext := filepath.Ext(filename)
	return ext == ".json" || ext == ".json"
}

// ReadYamlDir 读取yaml文件夹中所有的文件内容
func ReadYamlDir(dir string) (map[string][]map[string]interface{}, error) {
	var (
		metas = make(map[string][]map[string]interface{})
		mu    sync.Mutex
		wg    sync.WaitGroup
	)
	// 遍历目录及子目录
	err := filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error {
		if err != nil {
			return err
		}
		// 跳过目录和非YAML文件
		if d.IsDir() || !isYamlFile(path) {
			return nil
		}

		wg.Add(1)
		go func(p string) {
			defer wg.Done()
			// 解析YAML文件
			content, err := ReadYamlFileContent(p)
			if err != nil {
				log.Printf("文件 %s解析失败: %v", p, err)
				return
			}
			// 添加到结果集（加锁保证线程安全）
			mu.Lock()
			fileName := filepath.Base(p)
			if strings.Contains(fileName, ".json") {
				fileName = strings.Replace(fileName, ".json", "", -1)
			}
			metas[fileName] = content
			mu.Unlock()
		}(path)

		return nil
	})

	wg.Wait() // 等待所有goroutine完成
	return metas, err
}

// ReadYamlFileContent 读取yaml文件内容
func ReadYamlFileContent(fileUri string) ([]map[string]interface{}, error) {
	data, err := os.ReadFile(fileUri)
	if err != nil {
		return nil, fmt.Errorf("读取文件失败: %w", err)
	}
	var content []map[string]interface{}
	if err := yaml.Unmarshal(data, &content); err != nil {
		return nil, fmt.Errorf("解析失败: %w", err)
	}
	return content, nil
}

// isYamlFile 检查是否为YAML文件
func isYamlFile(path string) bool {
	ext := strings.ToLower(filepath.Ext(path))
	return ext == ".yaml" || ext == ".yml"
}
